package fire.and.near.challenger;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBar.Tab;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.Toast;

import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.InterstitialAd;
import com.google.android.gms.ads.purchase.InAppPurchase;
import com.google.android.gms.ads.purchase.InAppPurchaseListener;

import fire.and.near.challenger.camera.CameraHelper;
import fire.and.near.challenger.database.ChallengeModel;
import fire.and.near.challenger.database.ChallengeStatus;
import fire.and.near.challenger.database.DatabaseActivity;
import fire.and.near.challenger.database.DatabaseAsyncTask;
import fire.and.near.challenger.database.DatabaseAsyncTask.DatabaseQueryOptions;
import fire.and.near.challenger.database.DatabaseResponse;
import fire.and.near.challenger.database.FriendModel;
import fire.and.near.challenger.database.ProfileManager;
import fire.and.near.challenger.database.TableConstants.ChallengesTable;
import fire.and.near.challenger.database.TableConstants.FriendsTable;
import fire.and.near.challenger.database.limit.ChallengeConstraint;
import fire.and.near.challenger.facebook.FacebookActionAdapter;
import fire.and.near.challenger.facebook.FacebookHelper;
import fire.and.near.challenger.facebook.MessageBuilder;
import fire.and.near.challenger.facebook.MessageType;
import fire.and.near.challenger.fragments.ChallengeFriendFragment;
import fire.and.near.challenger.fragments.ChallengesHistoryFragment;
import fire.and.near.challenger.fragments.MyChallengesFragment;
import fire.and.near.challenger.util.Consts;
import fire.and.near.challenger.web.HttpRequestSender;
import fire.and.near.challenger.web.HttpRequestSender.RequestOptions;
import fire.and.near.challenger.web.ServerResponse;
import fire.and.near.challenger.web.WebActivity;

public class MainActivity extends ActionBarActivity implements
		ActionBar.TabListener, DatabaseActivity, WebActivity {

	// awesome comment in main ;/

	private boolean isWorking = false;
	private boolean httpWorking = false;
	private FacebookHelper mFbHelper = null;
	private ChallengeConstraint challengeConstraint = null;

	private List<ChallengeModel> myChallenges = null;
	private List<ChallengeModel> historyChallenges = null;
	private boolean myChallengesLoaded = false;
	private boolean historyChallengesLoaded = false;
	private boolean isFirstUse = false;

	List<ChallengeModel> mChallengesList = null;
	private Fragment mContentFragment = null;
	private FriendModel challenged = null;
	private String description = null;
	private int selectedChallengeType = 0;

	private long mFbId = 0;

	private String mCurrentPhotoPath;

	private AdView adView;
	private InterstitialAd interstitial;
	private final String MY_AD_UNIT_ID = "ca-app-pub-7930398005170773/7606669242";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		final Activity self = this;

		adView = (AdView) this.findViewById(R.id.adView);
		AdRequest adRequest = new AdRequest.Builder().addTestDevice(
				AdRequest.DEVICE_ID_EMULATOR).build();

		// Start loading the ad in the background.
		adView.loadAd(adRequest);
		
		interstitial = new InterstitialAd(this);
	    interstitial.setAdUnitId(MY_AD_UNIT_ID);
	    interstitial.setAdListener(new AdListener() {
	    	@Override
	    	public void onAdClosed() {
	    		if (self != null) {
	    			self.finish();
	    		}
	    		super.onAdClosed();
	    	}
		});
	    
	    AdRequest adRequestInt = new AdRequest.Builder().addTestDevice(
	    		AdRequest.DEVICE_ID_EMULATOR).build();

	    // Begin loading your interstitial.
	    interstitial.loadAd(adRequestInt);


		isFirstUse = true;

		mFbHelper = LoginActivity.mFbHelper;
		challengeConstraint = new ChallengeConstraint(this);

		initFbId();

		ActionBar actionBar = getSupportActionBar();
		actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
		actionBar.setDisplayShowHomeEnabled(false);
		actionBar.setDisplayShowTitleEnabled(false);

		actionBar
				.addTab(actionBar.newTab().setText(R.string.my_challenges)
						.setCustomView(R.layout.my_challenges_tab)
						.setTabListener(this));
		actionBar.addTab(actionBar.newTab().setText(R.string.challenge)
				.setCustomView(R.layout.challenge_friend_tab)
				.setTabListener(this));
		actionBar.addTab(actionBar.newTab().setText(R.string.history)
				.setCustomView(R.layout.history_tab).setTabListener(this));
	}
	
	@Override
	public void onBackPressed() {

		if (interstitial.isLoaded()) {
	    	interstitial.show();
	    }

		//finish();
		
		super.onBackPressed();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main_menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		int id = item.getItemId();
		if (id == R.id.action_logout) {
			if (HttpRequestSender.isNetworkAvailable(this)) {
				LoginActivity.mFbHelper.logout();
			}

			finish();
			return true;
		}

		if (id == R.id.action_details) {
			Intent i = new Intent(this, UserDetailsActivity.class);
			startActivity(i);

			return true;
		}

		return super.onOptionsItemSelected(item);
	}

	@Override
	public void onTabReselected(Tab arg0, FragmentTransaction arg1) {
		Log.i("MAINACT", "onTabReselect"); // //
		if (isFirstUse) {
			isFirstUse = false;
			return;
		}
		onTabSelected(arg0, arg1);
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		outState.putLong(FriendsTable.FB_ID, this.mFbId);

		super.onSaveInstanceState(outState);
	}

	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		this.mFbId = savedInstanceState.getLong(FriendsTable.FB_ID);

		super.onRestoreInstanceState(savedInstanceState);
	}

	@Override
	protected void onResume() {
		Log.i("MAINACT", "onResume"); // //

		if (myChallengesLoaded) {
			myChallengesLoaded = false;
		}
		if (historyChallengesLoaded) {
			historyChallengesLoaded = false;
		}

		int pos = getSupportActionBar().getSelectedTab().getPosition();

		if (pos == 1) {
			Log.i("RESTORE WE", "FF");
			restoreChallengeFriendTabState();
		}

		getSupportActionBar().getTabAt(pos).select();
		
		if (adView != null) {
			adView.resume();
		}

		super.onResume();
	}

	@Override
	protected void onPause() {
		saveChallengeFriendTabState();

		if (adView != null) {
			adView.pause();
		}
		super.onPause();
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();

		if (adView != null) {
			adView.destroy();
		}
	}

	private void initFbId() {
		ProfileManager profileManager = new ProfileManager(this);
		this.mFbId = profileManager.getFbId();
	}

	@Override
	public void onTabSelected(Tab tab, FragmentTransaction arg1) {

		Log.i("MAINACT", "onTabSelected"); // //
		if (tab.getPosition() != 1) {
			saveChallengeFriendTabState();
		}

		switch (tab.getPosition()) {
		case 0:
			mContentFragment = new MyChallengesFragment();
			if (!this.myChallengesLoaded) {
				new DatabaseAsyncTask(this, DatabaseQueryOptions.MY_CHALLENGES)
						.execute(this.mFbId);
			} else {
				((MyChallengesFragment) this.mContentFragment)
						.setChallenges(this.myChallenges);
			}
			break;
		case 1:
			mContentFragment = new ChallengeFriendFragment();

			Bundle args = new Bundle();
			args.putString(ChallengesTable.DESCRIPTION, description);
			args.putInt(ChallengesTable.CHALLENGE_TYPE, selectedChallengeType);
			if (challenged != null && challenged.getFbID() != 0) {
				args.putString(FriendsTable.NAME, challenged.getName());
			}
			if (mCurrentPhotoPath != null) {
				args.putString(ChallengesTable.PHOTO_PATH, mCurrentPhotoPath);
			}

			mContentFragment.setArguments(args);
			break;
		case 2:
			mContentFragment = new ChallengesHistoryFragment();
			if (!this.historyChallengesLoaded) {
				new DatabaseAsyncTask(this,
						DatabaseQueryOptions.HISTORY_CHALLENGES)
						.execute(this.mFbId);
			} else {
				((ChallengesHistoryFragment) this.mContentFragment)
						.setChallenges(this.historyChallenges);
			}
			break;
		}

		getSupportFragmentManager().beginTransaction()
				.replace(R.id.content, mContentFragment).commit();
	}

	private void saveChallengeFriendTabState() {
		EditText et = ((EditText) findViewById(R.id.editText_description));
		if (et != null) {
			description = et.getText().toString();
		}

		Spinner sp = ((Spinner) findViewById(R.id.spinner_challengeType));
		if (sp != null) {
			selectedChallengeType = sp.getSelectedItemPosition();
		}
	}

	private void restoreChallengeFriendTabState() {
		EditText et = ((EditText) findViewById(R.id.editText_description));
		if (et != null && description != null) {
			et.setText(description);
		}

		Spinner sp = ((Spinner) findViewById(R.id.spinner_challengeType));
		if (sp != null) {
			sp.setSelection(selectedChallengeType);
		}
	}

	@Override
	public void onTabUnselected(Tab arg0, FragmentTransaction arg1) {

	}

	@SuppressWarnings("unchecked")
	@Override
	public void processDatabaseResponse(DatabaseResponse result) {
		if (result.isSuccessful()) {
			switch (result.getOption()) {
			case MY_CHALLENGES:
				if (this.mContentFragment instanceof MyChallengesFragment) {
					View lv = findViewById(R.id.listView_challenges);
					if (lv != null) {
						lv.setVisibility(View.VISIBLE);
					}
					
					View tv = findViewById(R.id.textView_nomychallenges);
					if (tv != null) {
						tv.setVisibility(View.GONE);
					}

					this.myChallenges = (List<ChallengeModel>) result.getData();
					((MyChallengesFragment) this.mContentFragment)
							.setChallengesAndAdapter(this.myChallenges);
					this.myChallengesLoaded = true;
				}
				break;
			case HISTORY_CHALLENGES:
				if (this.mContentFragment instanceof ChallengesHistoryFragment) {
					View lv = findViewById(R.id.listView_challenges);
					if (lv != null) {
						lv.setVisibility(View.VISIBLE);
					}
					
					View tv = findViewById(R.id.textView_nohistchallenges);
					if (tv != null) {
						tv.setVisibility(View.GONE);
					}

					this.historyChallenges = (List<ChallengeModel>) result
							.getData();
					((ChallengesHistoryFragment) this.mContentFragment)
							.setChallengesAndAdapter(this.historyChallenges);
					this.historyChallengesLoaded = true;

				}
				break;
			case INSERT_CHALLENGES:
				// challenge was successfully inserted in local
				// database
				if (HttpRequestSender.isNetworkAvailable(this)) {
					new HttpRequestSender(RequestOptions.UPLOAD_CHALLENGES,
							this).execute(mChallengesList);
				} else {
					HttpRequestSender.connectingToServerErrorMessage(this);

				}

				mCurrentPhotoPath = null;
				challenged = null;
				mChallengesList = null;
				break;
			case DEFAULT_CHALLENGE:

				View lv = findViewById(R.id.listView_challenges);
				if (lv != null) {
					lv.setVisibility(View.VISIBLE);
				}
				
				View tv = findViewById(R.id.textView_nomychallenges);
				if (tv != null) {
					tv.setVisibility(View.GONE);
				}

				if (this.myChallenges == null) {
					this.myChallenges = new ArrayList<ChallengeModel>();
				}
				this.myChallenges.add((ChallengeModel) result.getData());

				if (mContentFragment instanceof MyChallengesFragment) {

					((MyChallengesFragment) this.mContentFragment)
							.setChallengesAndAdapter(this.myChallenges);
				}

				challengeConstraint.incAvailable();

				((ListView) findViewById(R.id.listView_challenges))
						.setSelection(this.myChallenges.size() - 1);

				break;
			case DELETE_LAST_PENDING:

				((EditText) findViewById(R.id.editText_description))
						.setText("");
				((Button) findViewById(R.id.button_friendPicker))
						.setText(getString(R.string.friend_picker));
				((ImageView) findViewById(R.id.imageView_photo))
						.setImageDrawable(getResources().getDrawable(
								R.drawable.camera_placeholder));
				((Spinner) findViewById(R.id.spinner_challengeType))
						.setSelection(0);
				break;
			default:
				break;
			}
		} else {
			switch (result.getOption()) {
			case MY_CHALLENGES:
				View lv = findViewById(R.id.listView_challenges);
				if (lv != null) {
					lv.setVisibility(View.GONE);
				}
				View tv = findViewById(R.id.textView_nomychallenges);
				if (tv != null) {
					tv.setVisibility(View.VISIBLE);
				}
				
				showMessage("You have no uncompleted challenges.");
				if (result.getData() != null
						&& ((List<ChallengeModel>) result.getData()).size() == 0) {
					this.myChallenges = null;
					this.myChallengesLoaded = false;
				}
				break;
			case HISTORY_CHALLENGES:
				findViewById(R.id.listView_challenges).setVisibility(View.GONE);
				findViewById(R.id.textView_nohistchallenges).setVisibility(
						View.VISIBLE);
				showMessage("You have no challenges in your history.");
				break;
			case INSERT_CHALLENGES:
				showMessage("Something went wrong. :(");
				break;
			case DEFAULT_CHALLENGE:
				showMessage("Currently, there are no new challenges.");
				break;
			default:
				break;
			}
		}
	}

	@Override
	public void setDatabaseWorking(boolean working) {

	}

	public void getNewChallenge(View v) {
		if (challengeConstraint.isAvailable()) {
			new DatabaseAsyncTask(this, DatabaseQueryOptions.DEFAULT_CHALLENGE)
					.execute();
		} else {
			showMessage("You have reached the daily limit.");
		}
	}

	public void completeCustomChallenge(View v) {
		startActivity(new Intent(this, CustomChallengeActivity.class));
	}

	public void pickFriend(View v) {
		if (!HttpRequestSender.isNetworkAvailable(this)) {
			HttpRequestSender.connectingToServerErrorMessage(this);
			return;
		}

		if (isWorking) {
			return;
		}

		startActivityForResult(new Intent(this, FriendPickerActivity.class),
				FriendPickerActivity.FRIEND_REQUEST_CODE);
	}

	public void takePicture(View v) {

		if (isWorking) {
			return;
		}

		saveChallengeFriendTabState();
		mCurrentPhotoPath = CameraHelper.dispatchTakePictureIntent(this);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {

		if (requestCode == FriendPickerActivity.FRIEND_REQUEST_CODE) {
			if (resultCode == RESULT_OK) {
				Bundle extras = data.getExtras();
				String name = extras.getString(FriendsTable.NAME);
				Long fbId = extras.getLong(FriendsTable.FB_ID, 0);
				if (name != null) {
					this.challenged = new FriendModel(fbId, name);
					((Button) findViewById(R.id.button_friendPicker))
							.setText(this.challenged.getName());
				} else {
					Toast.makeText(this, "No friend selected",
							Toast.LENGTH_LONG).show();
				}
			}
		} else if (requestCode == CameraHelper.REQUEST_TAKE_PHOTO) {
			if (resultCode == RESULT_OK) {
				restoreChallengeFriendTabState();
				initImageView();
			} else {
				((ImageView) findViewById(R.id.imageView_photo))
						.setImageDrawable(getResources().getDrawable(
								R.drawable.camera_placeholder));
			}

		}
	}

	private void initImageView() {
		if (mCurrentPhotoPath == null) {
			return;
		}

		ImageView ivPreview = (ImageView) findViewById(R.id.imageView_photo);
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;

		BitmapFactory.decodeFile(mCurrentPhotoPath, options);

		int width = ivPreview.getWidth();
		int height = ivPreview.getHeight();

		Log.i("CompleteChallengeAct", "" + width + "x" + height);

		options = CameraHelper.makeSampleOptions(this, options, width, height);

		options.inJustDecodeBounds = false;

		final Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath,
				options);

		ivPreview.setImageBitmap(bitmap);
	}

	public void challengeFriend(View v) {

		if (!HttpRequestSender.isNetworkAvailable(this)) {
			HttpRequestSender.connectingToServerErrorMessage(this);
			return;
		}

		String description = ((EditText) findViewById(R.id.editText_description))
				.getText().toString();

		if (description.length() < Consts.MESSAGE_MIN_LENGTH) {
			Toast.makeText(
					this,
					"Challenge description can't be shorter than "
							+ Consts.MESSAGE_MIN_LENGTH + " letters",
					Toast.LENGTH_LONG).show();
			return;
		}

		if (this.challenged == null || this.challenged.getFbID() == 0) {
			Toast.makeText(this, "No friend selected", Toast.LENGTH_LONG)
					.show();
			return;
		}

		if (isWorking) {
			return;
		}

		isWorking = true;
		// show progress bar
		findViewById(R.id.progressBar).setVisibility(View.VISIBLE);

		ChallengeModel challenge = new ChallengeModel();
		challenge.setDescription(description);
		challenge.getChallenger().setFbID(this.mFbId);
		challenge.setChallengedID(this.challenged.getFbID());
		challenge
				.setChallengeType(((Spinner) findViewById(R.id.spinner_challengeType))
						.getSelectedItemPosition() + 1);
		challenge.setAccepted(false);
		challenge.setStatus(ChallengeStatus.PENDING_FOR_SERVER);
		mChallengesList = new ArrayList<ChallengeModel>();
		mChallengesList.add(challenge);
		new DatabaseAsyncTask(this, DatabaseQueryOptions.INSERT_CHALLENGES)
				.execute(mChallengesList);

		Bitmap bitmap = null;

		if (mCurrentPhotoPath != null) {
			bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath);
		}

		MessageBuilder msgBuilder = new MessageBuilder(
				challenge.getDescription(), null, Consts.DEFAULT_HASHTAG,
				MessageType.StartChallenge);

		Log.i("FRID", "" + challenge.getChallengedID());

		final Context context = this;

		mFbHelper.postStatusUpdate(this, msgBuilder.build(),
				"" + challenge.getChallengedID(), bitmap,
				new FacebookActionAdapter() {
					@Override
					public void onActionCompleted(com.facebook.Response response) {
						if (response.getError() == null) {
							Log.i("CHALLENGE FRIEND", "SUCCESS");
							mCurrentPhotoPath = null;
							challenged = null;
							Toast.makeText(context, "Posted on Facebook",
									Toast.LENGTH_SHORT).show();
						} else {
							Log.e("CHALLENGE FRIEND", "ERROR");
						}

						isWorking = false;
						// hide progress bar
						findViewById(R.id.progressBar).setVisibility(View.GONE);
						
						((EditText) findViewById(R.id.editText_description))
								.setText("");
						((Button) findViewById(R.id.button_friendPicker))
								.setText(getString(R.string.friend_picker));
						((ImageView) findViewById(R.id.imageView_photo))
								.setImageDrawable(getResources().getDrawable(
										R.drawable.camera_placeholder));
						((Spinner) findViewById(R.id.spinner_challengeType))
								.setSelection(0);
					};
				});
	}

	@Override
	public void processSeverResponse(ServerResponse response) {
		if (response.getStatusCode() == Consts.HTTP_CREATED) {
			new DatabaseAsyncTask(this,
					DatabaseQueryOptions.DELETE_LAST_PENDING)
					.execute(this.mFbId);
			Toast.makeText(this, "Challenge sent!", Toast.LENGTH_LONG).show();
		}
	}

	@Override
	public void setHttpWorking(boolean working) {
		this.httpWorking = working;
	}

	private void showMessage(String message) {
		Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
	}
}
